home *** CD-ROM | disk | FTP | other *** search
/ Aminet 8 / Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso / Aminet / util / misc / ClipHan_1_1.lha / Src / clip-handler.c
C/C++ Source or Header  |  1995-07-09  |  11KB  |  390 lines

  1. /*
  2. **    clip-handler.c
  3. **    DOS handler for Clipboard access
  4. **    Copyright © 1995 Michael Letowski
  5. */
  6.  
  7. #define __USE_SYSBASE
  8.  
  9. #include <exec/types.h>
  10. #include <exec/execbase.h>
  11. #include <exec/memory.h>
  12. #include <dos/dos.h>
  13. #include <dos/dosextens.h>
  14. #include <dos/filehandler.h>
  15. #include <libraries/iffparse.h>
  16. #include <devices/clipboard.h>
  17. #include <support/types.h>
  18. #include <support/exec.h>
  19. #include <support/dos.h>
  20.  
  21. #include <string.h>
  22. #include <stdlib.h>
  23.  
  24. #include <proto/exec.h>
  25. #include <proto/iffparse.h>
  26.  
  27. #include "clip-handler.rev.h"
  28.  
  29. #define DOS_NAME        "dos.library"
  30. #define DOS_VERN         37L
  31. #define IFFP_NAME        "iffparse.library"
  32. #define IFFP_VERN        37L
  33. #define CLIP_NAME        "clipboard.device"
  34.  
  35. STATIC CONST TEXT VersionString[]=
  36.     VERSION(PROG_NAME,PROG_VERSION,PROG_REVISION,PROG_DATE);
  37.  
  38. #define ID_FTXT            MAKE_ID('F','T','X','T')
  39. #define ID_CHRS            MAKE_ID('C','H','R','S')
  40.  
  41. #define PATH_SIZE        256
  42.  
  43. #define SetPktRes(pkt,res1,res2)    ((pkt)->dp_Res1=(res1),(pkt)->dp_Res2=(res2))
  44.  
  45. /* Library bases */
  46. struct ExecBase *SysBase;
  47. struct Library *IFFParseBase;
  48.  
  49. /*    Packet routines    */
  50. STATIC struct DosPacket *WaitPacket(struct MsgPort *port);
  51. STATIC VOID ReplyPacket(struct DosPacket *packet, struct MsgPort *port);
  52. STATIC VOID ReplyPacketRes(struct DosPacket *packet, struct MsgPort *port,
  53.                                                         LONG res1, LONG res2);
  54. STATIC VOID FlushPackets(struct MsgPort *port);
  55.  
  56. /*    clip-handler routines    */
  57. STATIC struct IFFHandle *OpenCH(struct DosPacket *packet);
  58. STATIC VOID CloseCH(struct IFFHandle *iff);
  59. STATIC LONG OpenInputCH(struct DosPacket *packet);
  60. STATIC LONG OpenOutputCH(struct DosPacket *packet);
  61. STATIC LONG OpenUpdateCH(struct DosPacket *packet);
  62. STATIC LONG CloseIOUCH(struct DosPacket *packet);
  63. STATIC VOID ReadClipboard(struct DosPacket *packet);
  64. STATIC VOID WriteClipboard(struct DosPacket *packet);
  65. STATIC VOID SeekClipboard(struct DosPacket *packet);
  66. STATIC LONG IFF2DOS(LONG iffError);
  67.  
  68. SAVEDS LONG ClipHandler(VOID)
  69. {
  70.     struct Library *LocalIFFParseBase;
  71.  
  72.     struct Process *PR;
  73.     struct MsgPort *MP,*PacketPort;
  74.     struct DosPacket *Pkt;
  75.     struct DeviceNode *DevNode;
  76.     LBOOL Done=FALSE;
  77.     ULONG OpenCount=0;
  78.  
  79.     SysBase=*((struct ExecBase **)4);                            /* Set up SysBase */
  80.     PR=ThisProcessS;
  81.     MP=&PR->pr_MsgPort;
  82.  
  83.     if(PR->pr_CLI)                                                                /* Run from shell */
  84.         return(RETURN_FAIL);                                                /* Failure */
  85.  
  86.     Pkt=WaitPacket(MP);                                                        /* Get startup message */
  87.     try(DevNode=(struct DeviceNode *)BADDR(Pkt->dp_Arg3),NO_DEV);
  88.  
  89.     /* Open IFFParse */
  90.     unless(LocalIFFParseBase=OpenLibrary(IFFP_NAME,IFFP_VERN))
  91.         throw2(ReplyPacketRes(Pkt,MP,DOSFALSE,ERROR_INVALID_RESIDENT_LIBRARY),    NO_IFFPARSE);
  92.     /* Create port */
  93.     unless(PacketPort=CreateMsgPort())
  94.         throw2(ReplyPacketRes(Pkt,MP,DOSFALSE,ERROR_NO_FREE_STORE),    NO_PORT);
  95.  
  96.     /* Set up global bases */
  97.     IFFParseBase=LocalIFFParseBase;                                /* Set up global bases */
  98.     DevNode->dn_Task=PacketPort;
  99.     Pkt->dp_Arg4=(LONG)PacketPort;
  100.     ReplyPacketRes(Pkt,PacketPort,DOSTRUE,Pkt->dp_Res2);
  101.  
  102.     while(!Done)
  103.     {
  104.         Pkt=WaitPacket(PacketPort);
  105.         switch(Pkt->dp_Type)
  106.         {
  107.             case ACTION_FINDINPUT:
  108.                 OpenCount+=OpenInputCH(Pkt);
  109.                 break;
  110.             case ACTION_FINDOUTPUT:
  111.                 OpenCount+=OpenOutputCH(Pkt);
  112.                 break;
  113. /*            case ACTION_FINDUPDATE:
  114.                 OpenCount+=OpenUpdateCH(Pkt);*/
  115.                 break;
  116.             case ACTION_END:
  117.                 OpenCount-=CloseIOUCH(Pkt);
  118.                 break;
  119.             case ACTION_READ:
  120.                 ReadClipboard(Pkt);
  121.                 break;
  122.             case ACTION_WRITE:
  123.                 WriteClipboard(Pkt);
  124.                 break;
  125. /*            case ACTION_SEEK:
  126.                 SeekClipboard(Pkt);*/
  127.                 break;
  128.             case ACTION_DIE:
  129.                 if(OpenCount)
  130.                     SetPktRes(Pkt,DOSFALSE,ERROR_OBJECT_IN_USE);
  131.                 else
  132.                 {
  133.                     SetPktRes(Pkt,DOSTRUE,0);
  134.                     Done=TRUE;
  135.                 }
  136.                 break;
  137.             case ACTION_IS_FILESYSTEM:
  138.                 SetPktRes(Pkt,DOSFALSE,0);
  139.                 break;
  140.             default:
  141.                 SetPktRes(Pkt,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
  142.                 break;
  143.         }
  144.         ReplyPacket(Pkt,PacketPort);
  145.     }
  146.     Forbid();                                                                            /* Disable task switching */
  147.     DevNode->dn_Task=NULL;                                                /* Switch off device */
  148.     FlushPackets(PacketPort);                                            /* Discard waiting packets */
  149.     UnLoadSeg(DevNode->dn_SegList);                                /* Unload code */
  150.     DevNode->dn_SegList=NULL;                                            /* And mark this fact */
  151.     Permit();                                                                            /* Enable task switching */
  152.  
  153.     catch(NO_PORT,            DeleteMsgPort(PacketPort));
  154.     catch(NO_IFFPARSE,    CloseLibrary(LocalIFFParseBase));
  155.     catch(NO_DEV,                );
  156.     return(0);
  157. }    /* ClipHandler */
  158.  
  159. STATIC struct DosPacket *WaitPacket(struct MsgPort *port)
  160. {
  161.     WaitPort(port);
  162.     return((struct DosPacket *)GetMsg(port)->mn_Node.ln_Name);
  163. }    /* WaitPacket */
  164.  
  165. STATIC VOID ReplyPacket(struct DosPacket *packet, struct MsgPort *port)
  166. {
  167.     struct MsgPort *ReplyPort=packet->dp_Port;
  168.  
  169.     packet->dp_Port=port;
  170.     packet->dp_Link->mn_Node.ln_Name=(STRPTR)packet;
  171.     PutMsg(ReplyPort,packet->dp_Link);
  172. }    /* ReplyPacket */
  173.  
  174. STATIC VOID ReplyPacketRes(struct DosPacket *packet, struct MsgPort *port,
  175.                                                         LONG res1, LONG res2)
  176. {
  177.     SetPktRes(packet,res1,res2);
  178.     ReplyPacket(packet,port);
  179. }    /* ReplyPacketRes */
  180.  
  181. STATIC VOID FlushPackets(struct MsgPort *port)
  182. {
  183.     struct DosPacket *Packet;
  184.  
  185.     while(Packet=(struct DosPacket *)GetMsg(port)->mn_Node.ln_Name)
  186.         ReplyPacketRes(Packet,port,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
  187. }    /* FlushPackets */
  188.  
  189. STATIC struct IFFHandle *OpenCH(struct DosPacket *packet)
  190. {
  191.     CHAR Name[PATH_SIZE];
  192.     STRPTR Str=(STRPTR)BADDR(packet->dp_Arg3);
  193.     struct FileHandle *Handle=FH(packet->dp_Arg1);
  194.     struct IFFHandle *IFF;
  195.     LONG Unit;
  196.  
  197.     SetPktRes(packet,DOSFALSE,0);
  198.     Handle->fh_Arg1=0;
  199.     Handle->fh_Port=NULL;                                                    /* Non-interactive file */
  200.  
  201.     memcpy(Name,&Str[1],Str[0]);                                    /* Copy data */
  202.     Name[Str[0]]='\0';                                                        /* NULL-terminate */
  203.  
  204.     Str=Name;
  205.     if(Str=strchr(Str,':'))                                                /* Device name given */
  206.         Str++;                                                                            /* Skip it */
  207.     Unit=atol(Str);                                                                /* Convert to unit number */
  208.  
  209.     unless(IFF=AllocIFF())
  210.         throw2(packet->dp_Res2=ERROR_NO_FREE_STORE,    NO_IFF);
  211.     unless(IFF->iff_Stream=(ULONG)OpenClipboard(Unit))
  212.         throw2(packet->dp_Res2=ERROR_NO_FREE_STORE,    NO_CLIPBOARD);    /* FIX: error */
  213.     InitIFFasClip(IFF);
  214.     Handle->fh_Arg1=(LONG)IFF;
  215.     packet->dp_Res1=DOSTRUE;
  216.     return(IFF);
  217.  
  218.     catch(FOO,                    );
  219.     catch(NO_CLIPBOARD,    CloseClipboard((struct ClipboardHandle *)IFF->iff_Stream));
  220.     catch(NO_IFF,                FreeIFF(IFF));
  221.     return(NULL);
  222. }    /* OpenCH */
  223.  
  224. STATIC VOID CloseCH(struct IFFHandle *iff)
  225. {
  226.     CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
  227.     FreeIFF(iff);
  228. }    /* CloseCH */
  229.  
  230. STATIC LONG OpenInputCH(struct DosPacket *packet)
  231. {
  232.     struct IFFHandle *IFF;
  233.     LONG Error;
  234.  
  235.     try(IFF=OpenCH(packet),                                                NO_HANDLE);
  236.     try(!(Error=OpenIFF(IFF,IFFF_READ)),                    NO_IFF);
  237.     try(!(Error=StopChunk(IFF,ID_FTXT,ID_CHRS)),    IFF_ERROR);
  238.     try(!(Error=ParseIFF(IFF,IFFPARSE_SCAN)),            IFF_ERROR);
  239.     return(1);                                                                        /* Open succesfull */
  240.  
  241.     catch(IFF_ERROR,    );
  242.     catch(NO_IFF,            CloseIFF(IFF));
  243.     SetPktRes(packet,DOSFALSE,IFF2DOS(Error));        /* Set result */
  244.     catch(NO_HANDLE,    CloseCH(IFF));
  245.     return(0);                                                                        /* Open failed */
  246. }    /* OpenInputCH */
  247.  
  248. STATIC LONG OpenOutputCH(struct DosPacket *packet)
  249. {
  250.     struct IFFHandle *IFF;
  251.     LONG Error;
  252.  
  253.     try(IFF=OpenCH(packet),                                                                                NO_HANDLE);
  254.     try(!(Error=OpenIFF(IFF,IFFF_WRITE)),                                                    NO_IFF);
  255.     try(!(Error=PushChunk(IFF,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN)),    IFF_ERROR);
  256.     try(!(Error=PushChunk(IFF,0,ID_CHRS,IFFSIZE_UNKNOWN)),                IFF_ERROR);
  257.     return(1);                                                                        /* Open succesfull */
  258.  
  259.     catch(IFF_ERROR,    );
  260.     catch(NO_IFF,            CloseIFF(IFF));
  261.     SetPktRes(packet,DOSFALSE,IFF2DOS(Error));        /* Set result */
  262.     catch(NO_HANDLE,    CloseCH(IFF));
  263.     return(0);                                                                        /* Open failed */
  264. }    /* OpenOutputCH */
  265.  
  266. STATIC LONG OpenUpdateCH(struct DosPacket *packet)
  267. {
  268.     struct IFFHandle *IFF;
  269.     LONG Error;
  270.  
  271.     try(IFF=OpenCH(packet),                                                NO_HANDLE);
  272.     try(!(Error=OpenIFF(IFF,IFFF_WRITE)),                    NO_IFF);
  273.     try(!(Error=StopChunk(IFF,ID_FTXT,ID_CHRS)),    IFF_ERROR);
  274.         /* FIX: Should use write mode here */
  275.     try(!(Error=ParseIFF(IFF,IFFPARSE_SCAN)),            IFF_ERROR);
  276.     return(1);                                                                        /* Open succesfull */
  277.  
  278.     catch(IFF_ERROR,    );
  279.     catch(NO_IFF,            CloseIFF(IFF));
  280.     SetPktRes(packet,DOSFALSE,IFF2DOS(Error));        /* Set result */
  281.     catch(NO_HANDLE,    CloseCH(IFF));
  282.     return(0);                                                                        /* Open failed */
  283. }    /* OpenUpdateCH */
  284.  
  285. STATIC LONG CloseIOUCH(struct DosPacket *packet)
  286. {
  287.     struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
  288.  
  289. #if 0
  290.     /* FIX:??? Check PopChunk() for errors */
  291.     if(ftst(IFF->iff_Flags,IFFF_WRITE))                        /* Write mode */
  292.         if(PopChunk(IFF)==0)                                                /* Close CHRS */
  293.             PopChunk(IFF);                                                        /* Close FTXT */
  294. #endif
  295.     CloseIFF(IFF);
  296.     CloseCH(IFF);
  297.     SetPktRes(packet,DOSTRUE,0);                                    /* Set result */
  298.     return(1);
  299. }    /* CloseIOUCH */
  300.  
  301. STATIC VOID ReadClipboard(struct DosPacket *packet)
  302. {
  303.     struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
  304.     STRPTR Buffer=(STRPTR)packet->dp_Arg2;
  305.     LONG Read=-1,Bytes=packet->dp_Arg3;
  306.  
  307.     SetPktRes(packet,-1,0);                                                /* Set result */
  308.  
  309.     Read=ReadChunkBytes(IFF,Buffer,Bytes);                /* Read into buffer */
  310.     if(Read<0)
  311.         packet->dp_Res2=IFF2DOS(Read);
  312.     else
  313.         packet->dp_Res1=Read;
  314. }    /* ReadClipboard */
  315.  
  316. STATIC VOID WriteClipboard(struct DosPacket *packet)
  317. {
  318.     struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
  319.     STRPTR Buffer=(STRPTR)packet->dp_Arg2;
  320.     LONG Written=-1,Bytes=packet->dp_Arg3;
  321.  
  322.     SetPktRes(packet,-1,0);                                                /* Set result */
  323.  
  324.     Written=WriteChunkBytes(IFF,Buffer,Bytes);        /* Write buffer */
  325.     if(Written<0)
  326.         packet->dp_Res2=IFF2DOS(Written);
  327.     else
  328.         packet->dp_Res1=Written;
  329. }    /* WriteClipboard */
  330.  
  331. STATIC VOID SeekClipboard(struct DosPacket *packet)
  332. {
  333.     struct IFFHandle *IFF=(struct IFFHandle *)packet->dp_Arg1;
  334.     struct ContextNode *CN;
  335.     LONG Offset=packet->dp_Arg2,OffsetType=packet->dp_Arg3;
  336.     LONG OldPos,NewPos=-1;
  337.  
  338.     SetPktRes(packet,-1,ERROR_SEEK_ERROR);                /* Set result */
  339.  
  340.     unless(CN=CurrentChunk(IFF))
  341.         return;
  342.     unless(CN->cn_Type==ID_FTXT && CN->cn_ID==ID_CHRS)
  343.         return;
  344.  
  345.     switch(OffsetType)
  346.     {
  347.         case OFFSET_BEGINNING:
  348.             NewPos=Offset;
  349.             break;
  350.         case OFFSET_CURRENT:
  351.             NewPos=CN->cn_Scan+Offset;
  352.             break;
  353.         case OFFSET_END:
  354.             NewPos=CN->cn_Size-Offset;
  355.             break;
  356.     }
  357.     if(NewPos>0 && NewPos<CN->cn_Size)                        /* Can seek */
  358.     {
  359.         OldPos=CN->cn_Scan;
  360.         CN->cn_Scan=NewPos;
  361.         SetPktRes(packet,OldPos,0);
  362.     }
  363. }    /* SeekClipboard */
  364.  
  365. STATIC LONG IFF2DOS(LONG iffError)
  366. {
  367.     LONG DOSError=ThisProcessS->pr_Result2;
  368.  
  369.     unless(DOSError)                                                            /* Error not set */
  370.         switch(iffError)
  371.         {
  372.             case IFFERR_NOTIFF:    DOSError=ERROR_OBJECT_NOT_FOUND;    break;
  373.             case IFFERR_NOMEM:    DOSError=ERROR_NO_FREE_STORE;            break;
  374.             case IFFERR_SEEK:        DOSError=ERROR_SEEK_ERROR;                break;
  375.             case IFFERR_NOHOOK:    DOSError=ERROR_NOT_IMPLEMENTED;        break;
  376.             default:                        DOSError=ERROR_OBJECT_WRONG_TYPE;    break;
  377.         }
  378.     return(DOSError);
  379. }    /* IFF2DOS */
  380.  
  381. #if 0
  382. STATIC LONG SeekChunk(struct IFFHandle *iff, LONG offset)
  383. {
  384.     struct IFFStreamCmd Cmd=
  385.     {
  386.         IFFCMD_SEEK,    NULL,    offset
  387.     };    /* Cmd */
  388.     return(CallHookPkt((struct Hook *)(iff+1),iff,&Cmd));
  389. }    /* SeekChunk */
  390. #endif